#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "../inc/stack.h"
#include "../inc/log.h"
#include "../inc/defs.h"

#define INI_DIM 20

struct stackCDT
{
	stackElementT * data;
	int cant;
	int dim;
};

stackADT
NewStack(void)
{
	stackADT stack = NULL;

	if ( (stack = malloc(sizeof(struct stackCDT))) != NULL )
		stack -> cant = 0;

    if ( (stack -> data = calloc(INI_DIM, sizeof(stackElementT))) == NULL )
    {
        Fatal("NewStack@stackADT.c - not enough memory\n");
        return NULL;
    }

    stack -> dim = INI_DIM;
	return stack;
}

void
FreeStack(stackADT stack)
{
	if (stack == NULL)
		return;

    memset(stack -> data, 0, stack -> dim * sizeof(stackElementT));
    free(stack -> data);
	free(stack);
}

int
StackIsEmpty(stackADT stack)
{
	if (stack == NULL)
		return -1;

	return stack -> cant == 0;
}

int
Push(stackADT stack, stackElementT element)
{
    stackElementT * aux;
    
	if (stack == NULL || element == NULL)
		return 0;

	if (stack -> cant == stack -> dim)
	{
	    if ( (aux = realloc(stack -> data, stack -> dim * 2 * sizeof(stackElementT))) == NULL )
	    {
	        Fatal("Push@stackADT.c - Not enough memory\n");
	        return 0;
	    }
	    stack -> data = aux;
    }
    
    stack -> data[stack -> cant++] = element;

	return 1;
}

stackElementT
Pop(stackADT stack)
{
	if (stack == NULL)
		return NULL;

	if ( !StackIsEmpty(stack) )
		return stack -> data[--stack -> cant];
	else
		return NULL;
}

stackElementT
Tope(stackADT stack)
{
	if (stack == NULL)
		return NULL;

	if ( !StackIsEmpty(stack) )
		return stack -> data[stack -> cant - 1];
	else
		return NULL;
}
